/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;
using System.Configuration;
using VSLangProj80;
using System.Xml;
using DaveSexton.DocProject.Sandcastle.Resources;

namespace DaveSexton.DocProject.Sandcastle.Configuration
{
	public sealed class Presentation : ConfigurationElement
	{
		#region Public Properties
		public static readonly string TopicDesignerStyleSheetFileName = "TopicDesigner.css";

		public IDocProject ImportFrom
		{
			get
			{
				return importFrom;
			}
			set
			{
				if (value != null && !SandcastleBuildEngineProvider.IsProjectValid(value))
					throw new InvalidOperationException(Resources.Errors.InvalidProjectBuildEngineType);

				importFrom = value;
			}
		}

		[ConfigurationProperty("name", IsRequired = true, IsKey = true)]
		public string Name
		{
			get
			{
				return this["name"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["name"] = value;
			}
		}

		[ConfigurationProperty("path", IsRequired = true)]
		public string Path
		{
			get
			{
				return this["path"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["path"] = value;
			}
		}

		[ConfigurationProperty("description", IsRequired = true)]
		public string Description
		{
			get
			{
				return this["description"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["description"] = value;
			}
		}

		[ConfigurationProperty("fxReflectionDataDirectory", IsRequired = false, DefaultValue = "")]
		[StringValidator(MinLength = 0)]
		public string ReflectionDataDirectory
		{
			get
			{
				return this["fxReflectionDataDirectory"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["fxReflectionDataDirectory"] = value;
			}
		}

		[ConfigurationProperty("referenceConfigFile",  DefaultValue = @"Configuration\sandcastle.config", IsRequired = true)]
		[StringValidator(MinLength = 1)]
		public string ReferenceConfigFile
		{
			get
			{
				return this["referenceConfigFile"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["referenceConfigFile"] = value;
			}
		}

		[ConfigurationProperty("conceptualConfigFile", DefaultValue = @"Configuration\conceptual.config", IsRequired = true)]
		[StringValidator(MinLength = 1)]
		public string ConceptualConfigFile
		{
			get
			{
				return this["conceptualConfigFile"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["conceptualConfigFile"] = value;
			}
		}

		[ConfigurationProperty("conceptualTemplates", DefaultValue = @"Templates\Sandcastle\Conceptual", IsRequired = true)]
		[StringValidator(MinLength = 1)]
		public string ConceptualTemplatesDirectory
		{
			get
			{
				string path = Environment.ExpandEnvironmentVariables(this["conceptualTemplates"] as string);

				Uri uri = new Uri(path, UriKind.RelativeOrAbsolute);

				if (uri.IsAbsoluteUri)
					return path;
				else
					return System.IO.Path.Combine(DocProjectEnvironment.InstallPath, path);
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["conceptualTemplates"] = value;
			}
		}

		/// <summary>
		/// Gets or sets the relative path to the XML content files directory, based from the project's presentation directory
		/// or the shared presentation directory.
		/// </summary>
		[ConfigurationProperty("contentDirectory", IsRequired = true)]
		public string ContentDirectory
		{
			get
			{
				return this["contentDirectory"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["contentDirectory"] = value;
			}
		}

		[ConfigurationProperty("contentItemsXPath", IsRequired = true)]
		public string ContentItemsXPath
		{
			get
			{
				return this["contentItemsXPath"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["contentItemsXPath"] = value;
			}
		}

		[ConfigurationProperty("contentDesignerItems", IsRequired = false)]
		[System.ComponentModel.TypeConverter(typeof(StringCollectionConverter))]
    public IEnumerable<string> ContentDesignerItems
		{
			get
			{
				return this["contentDesignerItems"] as IEnumerable<string>;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["contentDesignerItems"] = value;
			}
		}

		[ConfigurationProperty("xmlDocModelTransformationArgs", IsRequired = false)]
		public string XmlDocModelTransformationArgs
		{
			get
			{
				return this["xmlDocModelTransformationArgs"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["xmlDocModelTransformationArgs"] = value;
			}
		}

		[ConfigurationProperty("xmlDocModelTransformation", IsRequired = true)]
		public string XmlDocModelTransformation
		{
			get
			{
				return this["xmlDocModelTransformation"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["xmlDocModelTransformation"] = value;
			}
		}

		[ConfigurationProperty("xmlTocTransformation", IsRequired = true)]
		public string XmlTocTransformation
		{
			get
			{
				return this["xmlTocTransformation"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["xmlTocTransformation"] = value;
			}
		}

		[ConfigurationProperty("friendlyFileNamesTransformation", IsRequired = true)]
		public string FriendlyFileNamesTransformation
		{
			get
			{
				return this["friendlyFileNamesTransformation"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["friendlyFileNamesTransformation"] = value;
			}
		}

		[ConfigurationProperty("guidFileNamesTransformation", IsRequired = true)]
		public string GuidFileNamesTransformation
		{
			get
			{
				return this["guidFileNamesTransformation"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["guidFileNamesTransformation"] = value;
			}
		}

		[ConfigurationProperty("mediaDirectory", IsRequired = true)]
		public string MediaDirectory
		{
			get
			{
				return this["mediaDirectory"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["mediaDirectory"] = value;
			}
		}

		[ConfigurationProperty("cascadingStyleSheetsDirectory", IsRequired = true)]
		public string CascadingStyleSheetsDirectory
		{
			get
			{
				return this["cascadingStyleSheetsDirectory"] as string;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["cascadingStyleSheetsDirectory"] = value;
			}
		}

		[ConfigurationProperty("includeFolders", IsRequired = false)]
		[System.ComponentModel.TypeConverter(typeof(StringCollectionConverter))]
    public IEnumerable<string> IncludeFolders
		{
			get
			{
        return this["includeFolders"] as IEnumerable<string>;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["includeFolders"] = value;
			}
		}

		[ConfigurationProperty("includePresentationFolders", IsRequired = false)]
		[System.ComponentModel.TypeConverter(typeof(StringCollectionConverter))]
    public IEnumerable<string> IncludePresentationFolders
		{
			get
			{
        return this["includePresentationFolders"] as IEnumerable<string>;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				this["includePresentationFolders"] = value;
			}
		}
		#endregion

		#region Privated / Protected
		private IDocProject importFrom;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="PresentationProvider" /> class.
		/// </summary>
		public Presentation()
		{
		}
		#endregion

		#region Methods
		public static bool IsTopicDesignerFile(string file)
		{
			return string.Equals(System.IO.Path.GetFileName(file), TopicDesignerStyleSheetFileName, StringComparison.OrdinalIgnoreCase);
		}

		public static Presentation GetPresentation(IDocProject project)
		{
			if (project == null)
				throw new ArgumentNullException("project");

			string name = SandcastleProjectOptions.GetPresentationName(project);

			if (SandcastleBuildEngineProvider.Presentations.Contains(name))
				return SandcastleBuildEngineProvider.Presentations[name];
			else
				return null;
		}

		public ICollection<string> Import(IDocProject project)
		{
			SandcastleProjectOptions.SetPresentation(project, this);

			PresentationImporter importer = new PresentationImporter(project, this, importFrom);
			importer.Import();

			importFrom = null;

			return importer.Warnings;
		}

		public void ImportAllConfigurationFiles(IDocProject project)
		{
			PresentationImporter importer = new PresentationImporter(project, this, null);

			importer.ImportAllConfigurationFiles();
		}

		public void ImportConfigurationFile(IDocProject project, HelpTypes type)
		{
			PresentationImporter importer = new PresentationImporter(project, this, null);

			importer.ImportConfigurationFile(type);
		}
		#endregion
	}
}
